package com.wan37.logic.shop.handler;

import com.wan37.logic.backpack.weaponry.WeaponryManager;
import com.wan37.logic.component.Worker;
import com.wan37.logic.db.AsynDBManager;
import com.wan37.logic.domain.Result;
import com.wan37.logic.domain.entity.UserDO;
import com.wan37.logic.domain.entity.UserItemDO;
import com.wan37.logic.domain.vo.BackpackVO;
import com.wan37.logic.global.reference.SpringContextHolder;
import com.wan37.logic.handler.WorkerHandler;
import com.wan37.logic.shop.cache.ShopCache;
import com.wan37.logic.domain.vo.ItemVO;
import com.wan37.logic.domain.vo.WeaponryVO;
import com.wan37.logic.email.EmailManager;
import com.wan37.logic.listener.EventDispatcher;
import com.wan37.logic.listener.event.EventType;
import com.wan37.logic.listener.event.user.UserLoginEvent;
import com.wan37.logic.service.UserItemService;
import com.wan37.logic.service.UserService;
import com.wan37.logic.service.UserWeaponryService;
import com.wan37.logic.service.cache.*;
import com.wan37.logic.shop.cache.CommodityServiceCache;
import com.wan37.logic.shop.domain.vo.CommodityVO;
import com.wan37.logic.shop.domain.vo.ShopVO;
import com.wan37.logic.shop.service.CommodityService;
import com.wan37.logic.shop.service.ShopService;
import com.wan37.logic.utils.RouteUtils;
import com.wan37.logic.utils.XmlUtil;
import com.wan37.protobuf.constant.CommonShop;
import com.wan37.protobuf.constant.ShopLabel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : luoyong
 * @date : 2020-07-06 10:25
 **/
public class ShopHandler implements WorkerHandler {
    private final Logger logger = LoggerFactory.getLogger(ShopHandler.class);
    private UserServiceCache userServiceCache;
    private CommodityServiceCache commodityServiceCache;
    private RoleServiceCache roleServiceCache;
    private ItemServiceCache itemServiceCache;
    private WeaponryServiceCache weaponryServiceCache;
    private AsynDBManager asynDBManager;
    private UserItemService userItemService;
    private EmailManager emailManager;
    private WeaponryManager weaponryManager;
    private UserService userService;
    private RouteUtils routeUtils;
    private ShopCache shopCache;
    private ShopService shopService;
    private CommodityService commodityService;
    private String userId;
    private String commodityId;
    private int count;
    private String shopId;
    public ShopHandler(){}
    public ShopHandler(String userId, String commodityId, Integer count, String shopId) {
        this.userId = userId;
        this.commodityId = commodityId;
        this.count = count;
        this.shopId = shopId;
        this.shopService = SpringContextHolder.getBean("shopService");
        this.shopCache = SpringContextHolder.getBean("shopCache");
        this.commodityService = SpringContextHolder.getBean("commodityService");
        this.routeUtils = SpringContextHolder.getBean("routeUtils");
        this.userService = SpringContextHolder.getBean("userService");
        this.weaponryManager = SpringContextHolder.getBean("weaponryManager");
        this.emailManager = SpringContextHolder.getBean("emailManager");
        this.userItemService = SpringContextHolder.getBean("userItemService");
        this.asynDBManager = SpringContextHolder.getBean("asynDBManager");
        this.weaponryServiceCache = SpringContextHolder.getBean("weaponryServiceCache");
        this.itemServiceCache = SpringContextHolder.getBean("itemServiceCache");
        this.roleServiceCache = SpringContextHolder.getBean("roleServiceCache");
        this.commodityServiceCache = SpringContextHolder.getBean("commodityServiceCache");
        this.userServiceCache = SpringContextHolder.getBean("userServiceCache");
    }

    /**
     * 判断是否同一天
     */
    public void isCommonDay(String shopId) {
        ShopVO shopVO = shopCache.getShopInMap().get(shopId).getShopVO();
        long refreshTimeDay = shopVO.getRefreshTimeDay();
        long newDay = System.currentTimeMillis() / (24 * 3600000);
        if (refreshTimeDay != newDay) {
            refreshShop(shopId);
            shopVO.setRefreshTimeDay(newDay);
            asynDBManager.distributeWork(shopId, ()->shopService.update(shopVO));
        }
        //更新在线玩家的商城
        for (String userId : userServiceCache.getUserServiceMap().keySet()) {
            EventDispatcher.getInstance().fireEvent(new UserLoginEvent(EventType.LOGIN, userId));
        }
    }

    /**
     * 每天商城可购买数量更新
     * @param shopId
     */
    private void refreshShop(String shopId) {
        for (CommodityVO commodityVO : shopCache.getShopInMap().get(shopId).getCommodityVOMap().values()){
            commodityVO.setNumber(commodityServiceCache.getCommodityInMap()
                    .get(commodityVO.getCommodityId()).getCommodityConfigVO().getNumber());
            asynDBManager.distributeWork(shopId, ()->commodityService.update(commodityVO));
        }
        logger.info("商城信息刷新成功！");
    }

    @Override
    public void execute(Worker worker) throws Exception {
        //判断是否隔天
        isCommonDay(shopId);
        UserServiceCache.User user = userServiceCache.getUserServiceMap().get(userId);
        CommodityVO commodityVO = shopCache.getShopInMap().get(shopId).getCommodityVOMap().get(commodityId);
        CommodityServiceCache.CommodityIn commodityIn = commodityServiceCache.getCommodityInMap().get(commodityId);
        if (commodityIn.getCommodityConfigVO().getLevelLimit() > roleServiceCache.getRoleServiceMap()
                .get(user.getRoleIdList().get(0)).getRoleVO().getLevel()) {
            routeUtils.sendShopResponse(CommonShop.GAME_ERROR, "用户等级不够！", null, userId);
            return;
        }
        if (commodityVO.getNumber() <= 0) {
            routeUtils.sendShopResponse(CommonShop.GAME_ERROR, "没货了，明天再来买吧！", null, userId);
            return;
        }
        /**
         * 进行对应货币对应钱是否充足判断
         */
        if (commodityIn.getCommodityConfigVO().getMoneyType() == ShopLabel.MONEY_TYPE_GOLD) {
            if (user.getUserVO().getGold() >= commodityIn.getCommodityConfigVO().getMoney()) {
                user.getUserVO().setGold(user.getUserVO().getGold() - commodityIn.getCommodityConfigVO().getMoney());
                UserDO userDO = new UserDO(user.getUserVO());
                asynDBManager.distributeWork(userId, () -> userService.update(userDO));
                routeUtils.sendUserVO(user.getUserVO());
                commodityVO.setNumber(commodityVO.getNumber() - count);
                asynDBManager.distributeWork(shopId, ()->commodityService.update(commodityVO));
            } else {
                routeUtils.sendShopResponse(CommonShop.GAME_ERROR, "你没钱了，请充值就好！", null, userId);
                return;
            }
        } else {
            if (user.getUserVO().getIngot() >= commodityIn.getCommodityConfigVO().getMoney()) {
                user.getUserVO().setIngot(user.getUserVO().getIngot() - commodityIn.getCommodityConfigVO().getMoney());
                UserDO userDO = new UserDO(user.getUserVO());
                asynDBManager.distributeWork(userId, () -> userService.update(userDO));
                routeUtils.sendUserVO(user.getUserVO());
                commodityVO.setNumber(commodityVO.getNumber() - count);
                asynDBManager.distributeWork(shopId, ()->commodityService.update(commodityVO));
            } else {
                routeUtils.sendShopResponse(CommonShop.GAME_ERROR, "你没钱了，请充值就好！", null, userId);
                return;
            }
        }

        /**
         * 购买的是物品
         */
        if (itemServiceCache.getItemServiceMap().containsKey(commodityId)) {
            ItemVO itemVO = userServiceCache.getUserServiceMap().get(userId).getItemVOMap().get(commodityId);
            if (itemVO == null) {
                itemVO = itemServiceCache.getItemServiceMap().get(commodityId).getItemVO();
                if (itemVO.getCount() == null) {
                    itemVO.setCount(count);
                } else {
                    itemVO.setCount(itemVO.getCount() + count);
                }
                UserItemDO userItemDO = new UserItemDO();
                userItemDO.setUserId(userId);
                userItemDO.setItemId(itemVO.getBackpackId());
                userItemDO.setCount(itemVO.getCount());
                userServiceCache.getUserServiceMap().get(userId).getItemVOMap().put(itemVO.getBackpackId(), itemVO);
                asynDBManager.distributeWork(userId, () -> userItemService.save(userItemDO));
            }else {
                itemVO.setCount(itemVO.getCount() + count);
                UserItemDO userItemDO = new UserItemDO();
                userItemDO.setUserId(userId);
                userItemDO.setItemId(itemVO.getBackpackId());
                userItemDO.setCount(itemVO.getCount());
                asynDBManager.distributeWork(userId, () -> userItemService.update(userItemDO));
            }
            routeUtils.sendShopResponse(CommonShop.GAME_SHOP_COMMODITY, "购买成功！", null, userId);
        }

        /**
         * 购买的是装备
         */
        if (weaponryServiceCache.getWeaponryServiceMap().containsKey(commodityId)) {
            WeaponryVO weaponryVO = weaponryServiceCache.getWeaponryServiceMap().get(commodityId).getWeaponryVO();
            List<WeaponryVO> newWeaponryList = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                WeaponryVO newWeaponryVO = new WeaponryVO(weaponryVO);
                newWeaponryList.add(newWeaponryVO);
            }
            //添加物品
            Result result = weaponryManager.emailAddWeaponry(userId, newWeaponryList);
            /**
             * 背包满了则发送邮件
             */
            if (result.getCode() == 0) {
                List<String> userIdList = new ArrayList<>();
                userIdList.add(userId);
                List<BackpackVO> backpackVOList = new ArrayList<>();
                backpackVOList.addAll(newWeaponryList);
                emailManager.sendEmail("背包已满，所有东西发你邮件了，请清理背包后进行领取操作。", "admin", userIdList, backpackVOList);
            }
            routeUtils.sendShopResponse(CommonShop.GAME_SHOP_COMMODITY, "购买成功！", null, userId);
        }
    }
}
